package com.item.manager.repository;


import com.google.common.base.Supplier;
import com.item.manager.Template;
import com.item.manager.serialize.TemplateAdaptor;

import java.util.List;
import java.util.NoSuchElementException;
import java.util.function.Predicate;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Suppliers.memoize;
import static java.lang.String.format;
import static java.util.stream.Collectors.toList;

/**
 * Repository for template entity, provides functionality for accessing templates.
 *
 * Created by Alexey on 3/2/2015.
 */
public class TemplateRepository {
    private final Supplier<List<TemplateAdaptor>> templateLoader;
    private final TemplateFunction templateFunction;

    public TemplateRepository(java.util.function.Supplier<List<TemplateAdaptor>> supplier) {
        this.templateFunction = new TemplateFunction();
        this.templateLoader = memoize(supplier::get);
    }

    public List<Template> all() {
        return templates();
    }

    public List<Template> byTag(String tag) {
        checkNotNull(tag);
        try {
            return templates().stream().filter(tag(tag)).collect(toList());
        } catch (NoSuchElementException e) {
            throw new RuntimeException(format("Not template name %s found", tag));
        }
    }

    public Template byName(String name) {
        checkNotNull(name);
        try {
            return templates().stream().filter(name(name)).findAny().get();
        } catch (NoSuchElementException e) {
            throw new RuntimeException(format("Not template name %s found", name));
        }
    }

    private Predicate<Template> tag(String tag) {
        return template -> template.allTags().stream().filter(t -> t.name().equals(tag)).findAny().isPresent();
    }

    private Predicate<Template> name(String name) {
        return t -> t.name().equals(name);
    }

    private List<Template> templates() {
        return templateLoader.get().stream().map(templateFunction).collect(toList());
    }

}
